package com.xyzh05.dao.hibernate;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Table;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Repository;

import com.xyzh05.dao.UserDao;
import com.xyzh05.model.User;
import com.xyzh05.util.PageBean;
import com.xyzh05.util.PageUtil;

/**
 * This class interacts with Spring's HibernateTemplate to save/delete and
 * retrieve User objects.
 * 
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a> Modified by
 *         <a href="mailto:dan@getrolling.com">Dan Kibler</a> Extended to
 *         implement Acegi UserDetailsService interface by David Carter
 *         david@carter.net Modified by <a href="mailto:bwnoll@gmail.com">Bryan
 *         Noll</a> to work with the new BaseDaoHibernate implementation that
 *         uses generics.
 */
@Repository("userDao")
public class UserDaoHibernate extends GenericDaoHibernate<User, Long> implements
		UserDao, UserDetailsService {

	/**
	 * Constructor that sets the entity to User.class.
	 */
	public UserDaoHibernate() {
		super(User.class);
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	public List<User> getUsers() {
		return getHibernateTemplate().find(
				"from User u order by upper(u.username)");
	}

	/**
	 * {@inheritDoc}
	 */
	public User saveUser(User user) {
		if (log.isDebugEnabled()) {
			log.debug("user's id: " + user.getId());
		}
		getHibernateTemplate().saveOrUpdate(user);
		// necessary to throw a DataIntegrityViolation and catch it in
		// UserManager
		getHibernateTemplate().flush();
		return user;
	}

	/**
	 * Overridden simply to call the saveUser method. This is happenening
	 * because saveUser flushes the session and saveObject of BaseDaoHibernate
	 * does not.
	 * 
	 * @param user
	 *            the user to save
	 * @return the modified user (with a primary key set if they're new)
	 */
	@Override
	public User save(User user) {
		return this.saveUser(user);
	}

	/**
	 * {@inheritDoc}
	 */
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		List users = getHibernateTemplate().find("from User where username=?",
				username);
		if (users == null || users.isEmpty()) {
			throw new UsernameNotFoundException("user '" + username
					+ "' not found...");
		} else {
			return (UserDetails) users.get(0);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public String getUserPassword(String username) {
		SimpleJdbcTemplate jdbcTemplate = new SimpleJdbcTemplate(
				SessionFactoryUtils.getDataSource(getSessionFactory()));
		Table table = AnnotationUtils.findAnnotation(User.class, Table.class);
		return jdbcTemplate.queryForObject(
				"select password from " + table.name() + " where username=?",
				String.class, username);

	}

	public User loadUserByUsernameAndPassword(String username, String password) {
		String hql = "select * from app_user a where a.username='" + username
				+ "' and a.password='" + password + "'";
		Query query = getSession().createSQLQuery(hql).addEntity(User.class);
		return (User) query.uniqueResult();
	}

	public Boolean userExist(String username) {
		String hql = "select * from app_user a where a.username='" + username
				+ "'";
		Query query = getSession().createSQLQuery(hql);
		return query.list() != null && query.list().size() > 0;
	}

	@SuppressWarnings("unchecked")
	public List<User> queryUserToAutoComplete(String keyword, String level) {
		List<Object> plist = new ArrayList<Object>();
		StringBuilder hql = new StringBuilder();
		hql.append("select new User(u.id, u.username, u.nickname) from User u where 1 = 1");
		if (keyword != null && !"".equals(keyword)) {
			hql.append(" and u.username like ?");
			plist.add("%" + keyword + "%");
		}
		if (level != null) {
			hql.append(" and bitand(u.level, ?) != 0 ");
			Long l = Long.valueOf(level);
			plist.add(l);
		}
		hql.append(" order by u.username");
		List<User> list = this.getHibernateTemplate().find(hql.toString(), plist.toArray());
		return list;
	}

	@SuppressWarnings("unchecked")
	public PageBean queryEditors(final PageBean pageBean) {
		return this.getHibernateTemplate().executeWithNativeSession(
			new HibernateCallback() {
				public Object doInHibernate(Session session) throws HibernateException, SQLException {
					StringBuilder sb = new StringBuilder();	
					String sbcount = " select count(u.id) from User u where bitand(u.level, 32) != 0 ";
					Query querycount = session.createQuery(sbcount);
					Object obj = querycount.uniqueResult();
					Long s = (Long) obj;				
					sb.append(" select new User(u.id, u.nickname, u.majorName, ");
					sb.append(" (select count(status) from VipService p where editor.id = u.id and status = 0), ");
					sb.append(" (select count(status) from VipService p where editor.id = u.id and status = 1), ");
					sb.append(" u.registtime ) from User u where bitand(u.level, 32) != 0 ");
					Query query = session.createQuery(sb.toString());
					int size = s.intValue();
					query.setFirstResult(pageBean.getPageNumber()-1);
					query.setMaxResults(pageBean.getObjectsPerPage());	
					List<User> users = query.list();
					pageBean.setList(users);
					pageBean.setFullListSize(size);
					pageBean.setPageNumber(pageBean.getPageNumber());
					pageBean.setTotalPages(PageUtil.getTotPageNum(pageBean.getObjectsPerPage(),size));  //总页数						
					return pageBean;
				}
			});
	}
	
}
